package com.wanjia.estate.utils;

import cn.hutool.core.text.CharSequenceUtil;
import com.wanjia.estate.annotation.Argument;
import com.wanjia.estate.exception.ControllerException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import static cn.hutool.core.text.CharSequenceUtil.isBlank;
import static cn.hutool.core.text.CharSequenceUtil.isNotBlank;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public final class ArgumentUtil {

    public static void appendArgument(Argument arg, String value, Collection<String> collection) {
        // 无效参数不处理
        if (arg == null || collection == null || value == null) {
            return;
        }

        // 去空处理
        value = value.trim();

        List<String> appends = new ArrayList<>();
        // 前缀参数添加
        if (arg.prefix().length > 0) {
            Stream.of(arg.prefix())
                    .filter(CharSequenceUtil::isNotBlank)
                    .forEach(appends::add);
        }

        if (isNotBlank(arg.key())) {
            if (isBlank(arg.join())) {
                appends.add(arg.key());
                appends.add(value);
            } else {
                appends.add(arg.key() + arg.join() + value);
            }
        } else if (isNotBlank(value)) {
            appends.add(value);
        }

        if (arg.suffix().length > 0) {
            Stream.of(arg.suffix())
                    .filter(CharSequenceUtil::isNotBlank)
                    .forEach(appends::add);
        }

        log.debug("append argument: {}", appends);
        collection.addAll(appends);
    }

    public static void appendArgument(Object obj, Collection<String> collection) {
        // 无效参数不处理
        if (obj == null || collection == null) {
            return;
        }

        // 遍历参数准备
        Class<?> objClass = obj.getClass();
        Field[] fields = objClass.getFields();
        Field[] declaredFields = objClass.getDeclaredFields();

        // 遍历字段处理
        Stream.of(fields, declaredFields)
                .flatMap(Stream::of)
                .forEach(f -> {
                    // 获取注解与过滤
                    Argument argument = f.getAnnotation(Argument.class);
                    if (argument == null) {
                        return;
                    }

                    // 数值获取与string化
                    boolean originAccessible = f.isAccessible();
                    String value;
                    try {
                        f.setAccessible(true);
                        value = Objects.toString(f.get(obj), null);
                    } catch (IllegalAccessException e) {
                        throw new ControllerException("反射获取数值异常", e);
                    } finally {
                        f.setAccessible(originAccessible);
                    }

                    // 参数构造
                    appendArgument(argument, value, collection);
                });
    }
}